﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Windows;
using System.Windows.Media.Animation;
using System.Windows.Media.Media3D;
using Bling.DSL;
using Bling.Properties;
using Bling.Util;
using Bling.Physics;
using Bling.Arrays;
using linq = Microsoft.Linq.Expressions;

namespace Bling.DSL {

  public abstract partial class Expr<T> {
    internal static void ProcessAll(Expr<T> from, Expr<T> to, CurrentIndex idx, Action<Expr<T>,Expr<T>> F) {
      for (int i = 0; i < idx.Container.Count; i++) {
        var eval = new ReplaceEval();
        eval.Replace[idx] = new Constant<int>(i);
        var from0 = (eval.Translate(from));
        var to0 = (eval.Translate(to));
        if (idx.Parent != null)
          ProcessAll(from0, to0, idx.Parent, F);
        else F(from0, to0);
      }
    }
  }

  public abstract partial class Expr {
    internal CurrentIndex FindLoop {
      get {
        var find = new MyFindLoop();
        return this.Visit(find);
      }
    }
    private class MyFindLoop : TranslateEval<MyFindLoop>, ExprVisitor<CurrentIndex> {
      public CurrentIndex Found = null;
      public override Expr<S> Translate<S>(Expr<S> value) {
        if (value is BasePhysicsPropertyValue<S>) {
          Translate(((BasePhysicsPropertyValue<S>)value).BaseContainer.Index.Underlying);
          Translate(((BasePhysicsPropertyValue<S>)value).Index.Underlying);
          return value;
        } else if (value is BaseBlockDependencyPropertyValue<S>) {
          Translate(((BaseBlockDependencyPropertyValue<S>)value).Index.Underlying);
          return value;
        } else if (value is CurrentIndex) {
          var value0 = (CurrentIndex)(object)value;
          if (Found == null) Found = value0;
          else if (value0.Is(Found)) Found = value0;
          else if (Found.Is(value0)) { } else throw new Exception("Unrelated loops: " + value0 + " vs. " + Found);
          return value;
        }
        return base.Translate<S>(value);
      }
      public CurrentIndex Visit<T>(Expr<T> value) {
        Translate(value);
        return Found;
      }
    }

  }
  public abstract partial class Brand<T, BRAND> {
    private class StepAssign : Assign {
      public Assign Copy() { return this; }
      public bool Accept<S>(Expr<S> lhs, Expr<S> rhs) {
        if (!(lhs is BasePhysicsPropertyValue<S>)) return false;
        var lhs0 = (BasePhysicsPropertyValue<S>)lhs;
        //if (!lhs0.IsAll) return false;
        var normal = lhs0.Normal;
        var hc = normal.GetHashCode();
        if (lhs0.World.HasStep.Contains(normal)) throw new Exception("already has step");
        lhs0.World.HasStep.Add(normal);
        lhs0.World.HasStepB.Add(lhs0.World.Constraints.Count);
        lhs0.World.Constraints.Add(new Constraint<S>(lhs0, rhs));
        return true;
      }
    }


    /// <summary>
    /// Create a step constraint for targetted physical value. The step function takes the physical value's current and old value and produces a new value. 
    /// Used step function is usually the formed from a call to VerletStep. 
    /// </summary>
    public Func<BRAND, BRAND, BRAND> Step {
      set {
        var old = new OldEval().Translate(this.Underlying);
        var result = value(this, ToBrand(old));
        if (!Underlying.Solve(new StepAssign(), result))
          throw new NotSupportedException();
      }
    }
    /// <summary>
    /// The old version of a stepped physical property.
    /// </summary>
    public BRAND Old {
      get { return ToBrand(new OldEval() { Check = true }.Translate(this.Underlying)); }
      set { Old.Bind = value; }
    }
    private class OldEval : TranslateEval<OldEval> {
      public bool Check = false;
      public override Expr<S> Translate<S>(Expr<S> value) {
        if (value is BasePhysicsPropertyValue<S>) {
          var value0 = (BasePhysicsPropertyValue<S>)value;
          var hc = value0.Normal.GetHashCode();

          if (Check && !value0.World.HasStep.Contains(value0.Normal)) throw new NotSupportedException();
          return new OldPhysicsValue<S>() { Underlying = value0 };
        }
        return base.Translate<S>(value);
      }
    }
    /// <summary>
    /// Initialize physical value with specified RHS value. 
    /// </summary>
    public BRAND Init {
      set {
        if (!Underlying.Solve(new InitAssign(), value))
          throw new NotSupportedException();
      }
    }
    private class InitAssign : Assign {
      public Assign Copy() { return this; }
      public bool Accept<S>(Expr<S> lhs, Expr<S> rhs) {
        if (lhs is BasePhysicsPropertyValue<S>) {
          var lhs0 = (BasePhysicsPropertyValue<S>)lhs;
          lhs0.World.Inits.Add(new Constraint<S>(lhs0, rhs));
          return true;
        }
        return false;
      }
    }
    /// <summary>
    /// For linking a value to a physical property.
    /// </summary>
    public class LinkX {
      internal Brand<T, BRAND> Target;
      /// <summary>
      /// Link LHS physical value to RHS linked value.
      /// </summary>
      /// <param name="UpdateLink">When true, the LHS physical value will be copied to the RHS linked value.  When false, the RHS linked value is copied to the LHS physical value.</param>
      /// <returns></returns>
      public BRAND this[BoolBl UpdateLink] {
        set {
          // slider.Value.Link[!slider.At.IsMouseOver] = slider.At.Value
          // compute the world...
          var findWorld = new FindWorld();
          findWorld.Translate(Target.Underlying);

          //Target.Underlying.Visit(findWorld);
          if (findWorld.World == null) {
            (UpdateLink == (new Constant<bool>(true).Bl())).CurrentValue.Assert();
            // do data binding instead. 
            value.Bind = Target;
            return;
            //throw new NotSupportedException("LHS must be a physics value");
          }
          if (findWorld.World.Links == null) throw new NotSupportedException("Link must be expressed before activated");
          findWorld.World.Links.Add(new World.Link<T>() {
            Physics = Target.Underlying,
            LinkValue = value.Underlying,
            UpdateLink = UpdateLink.Underlying,
          });


        }
      }
      /// <summary>
      /// Link LHS physical value to RHS linked value, always update by copying LHS physical value to RHS linked value. 
      /// </summary>
      public BRAND To {
        set {
          this[true] = value;
        }
      }
      private class FindWorld : TranslateEval<FindWorld> {
        public World World;
        public override Expr<S> Translate<S>(Expr<S> value) {
          if (value is BasePhysicsPropertyValue<S>) {
            var value0 = (BasePhysicsPropertyValue<S>)value;
            if (World != null && World != value0.World) throw new NotSupportedException("Cannot span multiple worlds");
            World = value0.World;
            return value;
          } else if (value is BaseBlockDependencyPropertyValue<S>) {
            var value0 = (BaseBlockDependencyPropertyValue<S>)value;
            if (World != null && World != value0.BaseContainer.Block.World) throw new NotSupportedException("Cannot span multiple worlds");
            World = value0.BaseContainer.Block.World;
            return value;
          }
          return base.Translate<S>(value);
        }
      }

    }
    /// <summary>
    /// Link physical value with a UI value, causing the values to be updated when the other changes.
    /// </summary>
    public LinkX Link {
      get { return new LinkX() { Target = this }; }
    }
  }

  public abstract partial class CoreBl<T, BRAND> {
    protected static readonly Operator<T, bool, T> GuardOp = new Operator<T, bool, T>(Markers.GuardMarker) {
      Expand = (t, g) => t,
      XInverse0 = (orig1, result, guard) => Expr<T>.ConditionOp.Make(guard, result, orig1)
    };
    protected static readonly Operator<T, double, T> RelaxOp = new Operator<T, double, T>(Markers.RelaxMarker) {
      Expand = (t, g) => t,
      XInverse0 = (orig1, result, t) => ToBrand(orig1).LerpX(ToBrand(result), t),
    };

    public static void TwoWayX(Cursor<Expr<T>> P, IntBl N, DoubleBl Strength, Func<BRAND,BRAND,bool,BRAND> F) {
      var Self = ToBrand(P.At);
      Self.Relax[Strength * .5, P.Index >= N] = F(Self, ToBrand(P.Prev[N]), true);
      Self.Relax[Strength * .5, P.Index < P.Count - N] = F(Self, ToBrand(P.Next[N]), false);
    }


    /// <summary>
    /// Weaken and guard physical constraints set on this value.
    /// </summary>
    public RelaxY Relax { get { return new RelaxY() { Target = this }; } }
    public class RelaxY {
      internal CoreBl<T, BRAND> Target;


      /// <summary>
      /// Partially satisfy goal up to t%.
      /// </summary>
      /// <param name="t">Percentage that the goal should be satisfied.</param>
      /// <returns>This value with an inverted Lerp (like restrict).</returns>
      public BRAND this[DoubleBl t] {
        get { return CoreBl<T, BRAND>.ToBrand(RelaxOp.Make(Target, t)); }
        set { this[t].Bind = value; }
      }
      /// <summary>
      /// Partially satisfy goal up to t% when guard is true.
      /// </summary>
      /// <param name="t">Percentage that the goal should be satisfied.</param>
      /// <param name="guard">Guard value.</param>
      /// <returns></returns>
      public BRAND this[DoubleBl t, BoolBl guard] {
        get { return CoreBl<T, BRAND>.ToBrand(RelaxOp.Make(GuardOp.Make(Target, guard), t)); }
        set { this[t, guard].Bind = value; }
      }
      /// <summary>
      /// Conditionally satisfy goal when guard is true.
      /// </summary>
      /// <param name="guard">Guard value.</param>
      /// <returns>This value with inverted condition.</returns>
      public BRAND this[BoolBl guard] {
        get { return CoreBl<T, BRAND>.ToBrand(GuardOp.Make(Target, guard)); }
        set { this[guard].Bind = value; }
      }

    }
  }

}
namespace Bling.Physics {
  public interface HasCurrentIndex {
    int Count { get; }
  }

  /// <summary>
  /// Represent current index used during vectorized constraint satisfication. Doesn't show up outside of physics module.
  /// </summary>
  internal class CurrentIndex : Expr<int> {
    public int Size { get { return Container.Count; } }
    public readonly HasCurrentIndex Container;
    public readonly CurrentIndex Parent;
    internal CurrentIndex(CurrentIndex Parent, HasCurrentIndex Container) { 
      this.Parent = Parent;
      this.Container = Container;
    }
    public bool Is(CurrentIndex Index) {
      if (Index == this) return true;
      if (Parent == null) return false;
      return Parent.Is(Index);
    }

    public override Eval<EVAL>.Info<int> Eval<EVAL>(Eval<EVAL> txt) {
      if (txt is PhysicsEval<EVAL>) 
        return (Eval<EVAL>.Info<int>)(object)((PhysicsEval<EVAL>)(object) txt).Physics.CurrentIndex(this);
      else if (txt is TranslateEval<EVAL>) return new TranslateEval<EVAL>.MyInfo<int>() { Value = this };
      else throw new NotSupportedException();
    }
    public override string ToString() { // current indices are branded.
      return "Current-" + Size + "[" + Container + "]";
    }
  }
  internal class DeltaTime : Expr<double> {
    public override Eval<EVAL>.Info<double> Eval<EVAL>(Eval<EVAL> txt) {
      if (txt is PhysicsEval<EVAL>)
        return (Eval<EVAL>.Info<double>)(object)((PhysicsEval<EVAL>)(object)txt).DeltaTime();
      else if (txt is TranslateEval<EVAL>) return new TranslateEval<EVAL>.MyInfo<double>() { Value = this };
      else throw new NotSupportedException();
    }
    public override string ToString() {
      return "DT";
    }
  }

  internal interface CodeDriver {}

  /// <summary>
  /// Represents a physical universe, all textures 
  /// are associates with one world, that then manages dynamic simulation.
  /// </summary>
  public class World  {
    public string Name;
    public World() {
      Name = "ns" + GetHashCode();
    }
    /// <summary>
    /// Elapsed time for current time step. 
    /// </summary>
    public DoubleBl DeltaTime {
      get { return new DeltaTime().Bl(); }
    }

    internal Func<PhysicsPropertyValue, BaseExpr> Nows;
    internal readonly List<PhysicsBlock> Blocks = new List<PhysicsBlock>();

    internal readonly List<Constraint> Constraints = new List<Constraint>();
    internal readonly List<Constraint> Inits = new List<Constraint>();
    /// <summary>
    /// List of actions to be executed in the UI thread on each time step.
    /// </summary>
    public readonly List<Action> UpdateInUI = new List<Action>();
    public readonly List<Action> AfterRelax = new List<Action>();

    internal readonly HashSet<PhysicsPropertyValue> HasStep = new HashSet<PhysicsPropertyValue>();
    internal readonly HashSet<int> HasStepB = new HashSet<int>();
    internal abstract class BaseLink {
      public abstract BaseExpr BasePhysics { get; }
      public abstract BaseExpr BaseLinkValue { get; }
      public Expr<bool> UpdateLink;
      public abstract bool SolvePhysics(Assign assign);
      public abstract bool SolveLinkValue(Assign assign);
      public abstract class LinkAssign : Assign {
        public abstract void Process<S>(DependencyPropertyValue<S> LHS, Expr<S> RHS);
        public abstract void Process<S>(BaseBlockDependencyPropertyValue<S> LHS, Expr<S> RHS);
        public Assign Copy() { return this; }
        public bool Accept<S>(Expr<S> LHS, Expr<S> RHS) {
          if (LHS is DependencyPropertyValue<S>) {
            var LHS0 = (DependencyPropertyValue<S>)LHS;
            Process(LHS0, RHS);
            return true;
          } else if (LHS is BaseBlockDependencyPropertyValue<S>) {
            var LHS0 = (BaseBlockDependencyPropertyValue<S>)LHS;
            Process(LHS0, RHS);
            return true;
          } else return false;
        }
      }
      public abstract class PhysicsAssign : Assign {
        public abstract void Process<S>(BasePhysicsPropertyValue<S> LHS, Expr<S> RHS);
        public abstract void Process<S>(BaseBlockDependencyPropertyValue<S> LHS, Expr<S> RHS);
        public abstract void Process<S>(DependencyPropertyValue<S> LHS, Expr<S> RHS);
        public Assign Copy() { return this; }
        public bool Accept<S>(Expr<S> LHS, Expr<S> RHS) {
          if (LHS is BasePhysicsPropertyValue<S>) {
            var LHS0 = (BasePhysicsPropertyValue<S>)LHS;
            Process(LHS0, RHS);
            return true;
          } else if (LHS is DependencyPropertyValue<S>) {
            var LHS0 = (DependencyPropertyValue<S>)LHS;
            Process(LHS0, RHS);
            return true;
          } else if (LHS is BaseBlockDependencyPropertyValue<S>) {
            var LHS0 = (BaseBlockDependencyPropertyValue<S>)LHS;
            Process(LHS0, RHS);
            return true;
          } else return false;
        }
      }
    }
    internal class Link<T> : BaseLink {
      public Expr<T> Physics;
      public Expr<T> LinkValue;
      public override BaseExpr BasePhysics { get { return Physics; } }
      public override BaseExpr BaseLinkValue { get { return LinkValue; } }
      public override bool SolvePhysics(Assign assign) {
        return Physics.Solve(assign, LinkValue);
      }
      public override bool SolveLinkValue(Assign assign) {
        return LinkValue.Solve(assign, Physics);
      }
    }
    internal List<BaseLink> Links = new List<BaseLink>();
  }


  internal interface PhysicsEval<EVAL> : DependencyPropertyEval<EVAL> where EVAL : Eval<EVAL> {
    // IntBl SubBlockIndex(CurrentIndex Parent, int Count, CurrentIndex index);
    // could be old or new. 
    PhysicsEvalHelper<EVAL> Physics { get; }
    Eval<EVAL>.Info<T> Access<T>(string name, Eval<EVAL>.Info<int> idx);
    Eval<EVAL>.Info<double> DeltaTime();
  }
  internal class PhysicsNameProvider {
    public readonly Dictionary<BaseExpr, int> Referenced = new Dictionary<BaseExpr, int>();
    public virtual string NameFor(PhysicsPropertyValue value) {
      var count = Count(value.BaseNormal);
      var ret = value.BaseContainer.Block.Name + "_" + value.PropertyName + "_" + count;
      if (value is OldPhysicsValue) ret = ret + "_OLD";
      return ret;
    }
    public virtual string ScratchFor(PhysicsPropertyValue value) {
      if (value is OldPhysicsValue) {
        return ScratchFor(((OldPhysicsValue)value).BaseUnderlying);
      }
      var name = NameFor(value);
      return name + "_X";
    }


    public virtual string NameFor(DependencyPropertyValue value) {
      var count = Count(value);
      var ret = "V" + value.Target.GetHashCode();
      return ret + "_" + value.WriteProperty.Name + "_" + count;
    }
    public virtual string NameFor(BaseBlockDependencyPropertyValue value) {
      var count = Count(value.BaseNormal);
      var ret = value.BaseContainer.Block.Name + "_" + value.BaseWriteProperty.Name + "_" + count;
      return ret;
    }
    private int Count(BaseExpr v) {
      if (v is OldPhysicsValue) return Count((BaseExpr)((OldPhysicsValue)v).BaseUnderlying);

      if (!Referenced.ContainsKey(v)) Referenced[v] = Referenced.Count;
      return Referenced[v];
    }
  }

  internal class PhysicsEvalHelper<EVAL> where EVAL : Eval<EVAL> {
    public readonly Dictionary<CurrentIndex, Eval<EVAL>.Info<int>> Indices = new Dictionary<CurrentIndex, Eval<EVAL>.Info<int>>();
    public CurrentIndex BodyIndex;
    public CurrentIndex SubBlockIndex;
    public Eval<EVAL>.Info<int> UseIndex;
    public PhysicsNameProvider Names = new PhysicsNameProvider();

    public Eval<EVAL> CoreEval { get { return (Eval<EVAL>)PhysicsEval; } }
    public PhysicsEval<EVAL> PhysicsEval { get; set; }

    public void Loop(CurrentIndex     BodyIndex, Eval<EVAL>.Info<int>    BlockValue,
                     CurrentIndex SubBlockIndex, Eval<EVAL>.Info<int> SubBlockValue,
                     Eval<EVAL>.Info<int> UseIndex) {
      this.BodyIndex = BodyIndex;
      this.SubBlockIndex = SubBlockIndex;
      this.UseIndex = UseIndex;
      Indices[BodyIndex] = BlockValue;
      Indices[SubBlockIndex] = SubBlockValue;
    }
    public Eval<EVAL>.Info<int> CurrentIndex(CurrentIndex idx) { return Indices[idx]; }
    public virtual Eval<EVAL>.Info<T> Eval<T>(BasePhysicsPropertyValue<T> value) {
      var useName = Names.NameFor(value);
      if (value.Index.Underlying.Equals(SubBlockIndex) &&
          value.BaseContainer.Index.Underlying.Equals(BodyIndex)) {
        return Access<T>(useName, UseIndex);
      }
      var idx = value.BaseContainer.Index * value.BaseCount + value.Index;
      return Access<T>(useName, idx.Underlying.Eval(CoreEval));
    }
    public virtual Eval<EVAL>.Info<T> Eval<T>(DependencyPropertyValue<T> value) { 
      return Access<T>(Names.NameFor(value), null);
    }
    public virtual Eval<EVAL>.Info<T> Eval<T>(BaseBlockDependencyPropertyValue<T> value) {
      return Access<T>(Names.NameFor(value), value.BaseContainer.Index.Underlying.Eval(CoreEval));
    }
    private Eval<EVAL>.Info<T> Access<T>(string name, Eval<EVAL>.Info<int> idx) {
      return PhysicsEval.Access<T>(name, idx);
    }
  }

  internal interface PhysicsPropertyValue : BaseExpr {
    World World { get; }
    PhysicsPropertyValue BaseNormal { get; }
    int AllocationSize { get; }
    CurrentIndex CurrentIndex { get; }
    PhysicsBlock.BaseBaseBlockValue BaseContainer { get; }
    int BaseCount { get; }
    IntBl Index { get; }
    OldPhysicsValue Old { get; }
    string PropertyName { get; }
  }
  internal abstract class Constraint {
    public abstract PhysicsPropertyValue BaseLHS { get; }
    public abstract Expr BaseRHS { get; }
    public abstract bool Solve(Assign assign);

  }
  internal class Constraint<T> : Constraint {
    public readonly BasePhysicsPropertyValue<T> LHS;
    public readonly Expr<T> RHS;
    public Constraint(BasePhysicsPropertyValue<T> LHS, Expr<T> RHS) {
      this.LHS = LHS; this.RHS = RHS;
    }
    public override PhysicsPropertyValue BaseLHS {
      get { return LHS; }
    }
    public override Expr BaseRHS {
      get { return RHS; }
    }
    public override bool Solve(Assign assign) {
      return LHS.Solve(assign, RHS);
    }
  }
  internal interface OldPhysicsValue : PhysicsPropertyValue {
    PhysicsPropertyValue BaseUnderlying {
      get; 
    }
  }
  internal class OldPhysicsValue<T> : BasePhysicsPropertyValue<T>, OldPhysicsValue {
    public BasePhysicsPropertyValue<T> Underlying;
    public PhysicsPropertyValue BaseUnderlying { get { return Underlying; } }
    public override string ToString() {
      return Underlying.ToString() + "-old";
    }
    public override PhysicsProperty<T> Property {
      get { return Underlying.Property; }
    }
    public override PhysicsBlock.BaseBaseBlockValue BaseContainer { get { return Underlying.BaseContainer; } }
    public override int GetHashCode() {
      return Underlying.GetHashCode();
    }
    public override bool Equals(object obj) {
      return (obj is OldPhysicsValue<T>) &&
        ((OldPhysicsValue<T>)obj).Underlying.Equals(Underlying);
    }
    public override IntBl Index {
      get { return Underlying.Index; }
    }
    public override int BaseCount {
      get { return Underlying.BaseCount; }
    }
    public override CurrentIndex CurrentIndex {
      get { return Underlying.CurrentIndex; }
    }
    public override int AllocationSize {
      get { return Underlying.AllocationSize; }
    }
    public override BasePhysicsPropertyValue<T> Normal {
      get { return new OldPhysicsValue<T>() { Underlying = Underlying.Normal }; }
    }
    public override World World { get { return Underlying.World; } }
    /*
    public override BasePhysicsPropertyValue<T> Denormal(int idx) {
      return new OldPhysicsValue<T>() { Underlying = Underlying.Denormal(idx) };
    }
     */
    public override OldPhysicsValue Old { get { throw new NotSupportedException(); } }
  }

  public abstract class PhysicsProperty {
    public abstract Type TypeOfS { get; }
  }

  /// <summary>
  /// Physical property of a block, body, body sub-block.
  /// </summary>
  public sealed class PhysicsProperty<S> : PhysicsProperty {
    public override Type TypeOfS {
      get { return typeof(S); }
    }
    /// <summary>
    /// Name of property.
    /// </summary>
    public readonly string Name;
    /// <summary>
    /// Group that property belongs to.
    /// </summary>
    public readonly PropertyGroup Group;
    internal PhysicsProperty(PropertyGroup Group, string Name) { 
      this.Name = Name;
      this.Group = Group;
    }
    internal PhysicsProperty(PhysicsBlock block, string Name) : this(block.BodyProperties, Name) {}

    public string BaseString { get { return Group.Name + "_" + Name; } }
  }
  /// <summary>
  /// Identifies a group of homogenous sub-blocks
  /// </summary>
  public sealed class PropertyGroup : HasCurrentIndex {
    /// <summary>
    /// Block that contains this sub block group.
    /// </summary>
    public readonly PhysicsBlock Block;
    /// <summary>
    /// Name of sub-block group.
    /// </summary>
    public readonly string Name;
    /// <summary>
    /// Number of elements in the sub-block per parent block.
    /// </summary>
    public int Count { get; private set; }

    public PhysicsProperty<S> NewProperty<S>(string name) { return new PhysicsProperty<S>(this, name); }

    /// <param name="Block">Containing block.</param>
    /// <param name="Name">Sub-block's name.</param>
    /// <param name="Count">Number of elements in sub-block per parent block.</param>
    public PropertyGroup(PhysicsBlock Block, string Name, int Count) {
      this.Name = Name;
      this.Block = Block;
      this.Count = Count;
      (Block.CurrentIndex != null).Assert();
      CurrentIndex = new CurrentIndex(Block.CurrentIndex, this);
    }
    public override string ToString() {
      return Block.ToString() + "_" + Name;
    }
    internal readonly CurrentIndex CurrentIndex;
  }


  internal abstract class BasePhysicsPropertyValue<T> : PropertyValue<T>, BindableExpr<T>, PhysicsPropertyValue, AssignNowExpr<T> {
    public abstract World World { get; }
    public abstract BasePhysicsPropertyValue<T> Normal { get; }

    public PhysicsPropertyValue BaseNormal { get { return Normal; } }
    public abstract PhysicsProperty<T> Property { get; }
    public string PropertyName { get { return Property.Name; } }
    public abstract int AllocationSize { get; }
    public bool BindWith(Expr<T> value) {
      World.Constraints.Add(new Constraint<T>(this, value));
      return true;
    }
    public virtual OldPhysicsValue Old { get { return new OldPhysicsValue<T>() { Underlying = this }; } }

    public override Eval<EVAL>.Info<T> Eval<EVAL>(Eval<EVAL> txt) {
      if (txt is PhysicsEval<EVAL>) {
        return ((PhysicsEval<EVAL>)txt).Physics.Eval<T>(this);
      } else if (World.Nows != null) {
        return ((Expr<T>)World.Nows(this)).Eval(txt);
      } else if (txt is LinqBindEval) {
        throw new NotImplementedException();
      }
      throw new NotImplementedException();
    }
    public abstract CurrentIndex CurrentIndex { get; }
    public abstract PhysicsBlock.BaseBaseBlockValue BaseContainer { get;  }
    public abstract int BaseCount { get; } // { throw new NotSupportedException(); } }
    public abstract IntBl Index { get; }
    // just delegate.
    public Action SetNow(Expr<T> value) {
      return ((AssignNowExpr<T>)World.Nows(this)).SetNow(value);
    }
    public Action<S> SetNow<S>(Expr<T> value, ParameterExpr<S> arg) {
      return ((AssignNowExpr<T>)World.Nows(this)).SetNow<S>(value, arg);
    }
    public Action<S,U> SetNow<S,U>(Expr<T> value, ParameterExpr<S> argA, ParameterExpr<U> argB) {
      return ((AssignNowExpr<T>)World.Nows(this)).SetNow<S,U>(value, argA, argB);
    }
    public Action<S, U, V> SetNow<S, U, V>(Expr<T> value, ParameterExpr<S> argA, ParameterExpr<U> argB, ParameterExpr<V> argC) {
      return ((AssignNowExpr<T>)World.Nows(this)).SetNow<S, U, V>(value, argA, argB, argC);
    }
    public Action<S, U, V, W> SetNow<S, U, V, W>(Expr<T> value, ParameterExpr<S> argA, ParameterExpr<U> argB, ParameterExpr<V> argC, ParameterExpr<W> argD) {
      return ((AssignNowExpr<T>)World.Nows(this)).SetNow<S, U, V, W>(value, argA, argB, argC, argD);
    }
    public bool SetNow(T value) {
      return ((AssignNowExpr<T>)World.Nows(this)).SetNow(value);
    }
  }


  /// <summary>
  /// Base physics block, refined further with various type parameters.
  /// </summary>
  public abstract class PhysicsBlock : System.Windows.UIElement, HasCurrentIndex { // can add dependency properties.  
    /// <summary>
    /// World that this physic's block belongs to.
    /// </summary>
    public readonly World World;
    /// <summary>
    /// Name of the physics block.
    /// </summary>
    public string Name;

    public override string ToString() { return Name; }


    /// <summary>
    /// Create a new physics block.
    /// </summary>
    /// <param name="World">World that owns block.</param>
    public PhysicsBlock(World World) {
      CurrentIndex = new CurrentIndex(null, this);
      this.World = World;
      World.Blocks.Add(this);
      BodyProperties = new PropertyGroup(this, "Body", 1);
      BlockProperties = new PropertyGroup(this, "Block", 0);
      Name = "B" + (GetHashCode() % 100);
    }
    /// <summary>
    /// Number of objects wrapped by block.
    /// </summary>
    public abstract int Count { get; } // { return BaseUnderlying.Length; } }
    protected internal virtual void Init() { }
    protected internal virtual void Activate() { }

    public struct BaseBaseBlockValue {
      public PhysicsBlock Block;
      public IntBl Index;
      public override string ToString() {
        return Block + "[" + Index + "]";
      }
      public override bool Equals(object obj) {
        if (obj is BaseBaseBlockValue) {
          var obj0 = (BaseBaseBlockValue)obj;
          var result = Block == obj0.Block;
          result = result && Index.Equals(obj0.Index);
          return result;
        }
        return base.Equals(obj);
      }
      public override int GetHashCode() {
        return Block.GetHashCode() + Index.GetHashCode();
      }
    }
    internal readonly PropertyGroup BodyProperties;
    internal readonly PropertyGroup BlockProperties;

    public PhysicsProperty<S> NewBodyProperty<S>(string name) {
      return BodyProperties.NewProperty<S>(name); 
    }
    public PhysicsProperty<S> NewBlockProperty<S>(string name) {
      return BlockProperties.NewProperty<S>(name);
    }

    // what about a block property?

    // lazy initialization.
    internal readonly CurrentIndex CurrentIndex;
    internal abstract Expr<S> GetProperty<S>(PhysicsProperty<S> p, IntBl BodyIndex, IntBl SubIndex);
    public Expr<S> GetProperty<S>(PhysicsProperty<S> p) {
      (p.Group == this.BlockProperties).Assert();
      return GetProperty<S>(p, 0, 0);
    }
    public abstract class BaseSubBlock {
      protected internal BaseBaseBlockValue Container { get; set;  }
      internal PropertyGroup Id;
      public IntBl Index { get; internal set; }
      public override string ToString() {
        return Container + "." + Id.Name + "[" + Index + "]";
      }
      public Expr<S> Property<S>(PhysicsProperty<S> p) {
        (p.Group == Id).Assert();
        return Container.Block.GetProperty<S>(p, Container.Index, Index);
      }
    }
    public abstract class SubBlock<SELF0> : BaseSubBlock where SELF0 : SubBlock<SELF0>, new() {
      public class NextPrev {
        internal SubBlock<SELF0> Parent;
        internal Func<IntBl, IntBl, IntBl> F;
        /// <summary>
        /// Return next or previous sub-block based with wrap around.
        /// </summary>
        /// <param name="offset">Offset of sub-block to access</param>
        /// <returns></returns>
        public SELF0 this[IntBl offset] {
          get {
            var block = new SELF0() {
              Id = Parent.Id,
              Container = Parent.Container,
              Index = F(Parent.Index, offset),
            };
            return block;
          }
        }
      }
      /// <summary>
      /// Access next sub-blocks.
      /// </summary>
      public NextPrev Next {
        get { return new NextPrev { Parent = this, F = (a, b) => (a + b).NormalizeUp(Id.Count), }; }
      }
      /// <summary>
      /// Access previous sub-blocks.
      /// </summary>
      public NextPrev Prev {
        get { return new NextPrev { Parent = this, F = (a, b) => (a - b).NormalizeDown(Id.Count), }; }
      }
    }
    public interface BaseSubBlockFactory<SubBlockT> where SubBlockT : SubBlock<SubBlockT>, new() {
      /// <summary>
      /// Access sub-block of specified group.
      /// </summary>
      /// <param name="index"></param>
      /// <returns></returns>
      SubBlockT this[IntBl index] { get; }
      /// <summary>
      /// Apply constraints to each sub-block in body. 
      /// </summary>
      /// <param name="F">Constraints to apply as closure.</param>
      void ForAll(Action<SubBlockT> F);
      /// <summary>
      /// Number of sub-blocks that this sub-block group has.
      /// </summary>
      int Count { get; }
    }
  }
  // stateless mixins. 
  public interface BaseHasBlockExtension<BLOCK> where BLOCK: PhysicsBlock<BLOCK>, BaseHasBlockExtension<BLOCK> {
    PhysicsBlock<BLOCK> Self { get; }
  }
  public interface BaseHasBlockExtension<BLOCK, EXTENSION> : BaseHasBlockExtension<BLOCK>
    where BLOCK : PhysicsBlock<BLOCK>, BaseHasBlockExtension<BLOCK, EXTENSION>
    where EXTENSION : BaseBlockExtension<EXTENSION, BLOCK> {
  }

  public interface HasBlockExtension<BLOCK, EXTENSION> : BaseHasBlockExtension<BLOCK,EXTENSION> 
    where BLOCK : PhysicsBlock<BLOCK>, HasBlockExtension<BLOCK, EXTENSION> 
    where EXTENSION : BlockExtension<EXTENSION,BLOCK> {}

  public interface BaseBlockExtension { }
  public interface BaseBlockExtension<BLOCK> : BaseBlockExtension where BLOCK : PhysicsBlock<BLOCK> { }
  public interface BaseBlockExtension<EXTENSION, BLOCK> : BaseBlockExtension<BLOCK> where BLOCK : PhysicsBlock<BLOCK> { }
  public abstract class BlockExtension : BaseBlockExtension { }
  public abstract class BlockExtension<BLOCK> : BlockExtension, BaseBlockExtension<BLOCK> where BLOCK : PhysicsBlock<BLOCK> {
    internal protected abstract void DoInit(BLOCK block);
    internal protected virtual void DoActivate(BLOCK block) { }
    protected void ForceInit<EXTENSION>(BLOCK block) where EXTENSION : BlockExtension<BLOCK> {
      block.ForceInit(typeof(EXTENSION));
    }
  }

 
  public abstract class BlockExtension<EXTENSION,BLOCK> : BlockExtension<BLOCK>, BaseBlockExtension<EXTENSION,BLOCK> where EXTENSION : BlockExtension<EXTENSION,BLOCK> where BLOCK : PhysicsBlock<BLOCK> {
    public BlockExtension(BLOCK block) {
      block.Register<EXTENSION>((EXTENSION) this);
    }
  }
  public abstract class PhysicsBlock<BLOCK> : PhysicsBlock, BaseHasBlockExtension<BLOCK> where BLOCK : PhysicsBlock<BLOCK>, BaseHasBlockExtension<BLOCK>{
    public PhysicsBlock(World World) : base(World) { }
    public PhysicsBlock<BLOCK> Self { get { return this; } }

    private readonly Dictionary<Type, BlockExtension<BLOCK>> Extensions = new Dictionary<Type, BlockExtension<BLOCK>>();
    private readonly HashSet<Type> Initialized = new HashSet<Type>();
    internal void Register<EXTENSION>(EXTENSION e) where EXTENSION : BlockExtension<EXTENSION,BLOCK> {
      Extensions[typeof(EXTENSION)] = e;
    }
    public EXTENSION Extension<EXTENSION>() where EXTENSION : BlockExtension<EXTENSION,BLOCK> {
      return (EXTENSION)(object) Extensions[typeof(EXTENSION)];
    }
    internal void ForceInit(Type type) {
      if (Initialized.Contains(type)) return;
      Initialized.Add(type);
      Extensions[type].DoInit((BLOCK) this);
    }
    /// <summary>
    /// Initialize extenions and this block. 
    /// </summary>
    protected internal override void Init() {
      base.Init();
      foreach (var v in Extensions) ForceInit(v.Key);
      CustomInit((BLOCK)this);
    }
    protected internal override void Activate() {
      foreach (var v in Extensions) v.Value.DoActivate((BLOCK) this);
      CustomActivate((BLOCK)this);
    }

    public Action<BLOCK> CustomInit = (block) => { };
    public Action<BLOCK> CustomActivate = (block) => { };

    internal struct BaseBlockValue {
      public BLOCK Block;
      public IntBl Index;
      public override string ToString() {
        return Block + "[" + Index + "]";
      }
      public static implicit operator BaseBaseBlockValue(BaseBlockValue bv) {
        return new BaseBaseBlockValue() { Block = bv.Block, Index = bv.Index };
      }
    }
    public interface BodyCursor<S> : Cursor<Expr<S>> {
      Body Body { get; }
      PhysicsProperty<S> Property { get; }
    }

    public interface Body {
      Body this[IntBl offset] { get; }
      CursorNextPrev<Body> Next { get; }
      CursorNextPrev<Body> Prev { get; }
      BaseSubBlockFactory<SubBlockT> SubBlock<SubBlockT>(PropertyGroup Id) where SubBlockT : SubBlock<SubBlockT>, new();
      IntBl Index { get; }
      BLOCK Block { get; }
      Expr<S> GetProperty<S>(PhysicsProperty<S> p);
      BodyCursor<S> Cursor<S>(PhysicsProperty<S> p);
    }
    public void ForAll(Action<Body> F) { F(new BaseBody() { Block0 = (BLOCK)this, Index0 = CurrentIndex }); }
    public Body this[IntBl idx] { get { return new BaseBody() { Block0 = (BLOCK) this, Index0 = idx }; } }



    internal class PhysicsPropertyValue<S> : BasePhysicsPropertyValue<S> {
      internal BaseBaseBlockValue Container;
      internal PhysicsProperty<S> BaseProperty;
      internal Expr<int> BaseIndex;
      public override IntBl Index { get { return BaseIndex; } }
      public override PhysicsProperty<S> Property { get { return BaseProperty; } }
      public override PhysicsBlock.BaseBaseBlockValue BaseContainer { get { return Container; } }
      public override int BaseCount { get { return BaseProperty.Group.Count; } }
      public override CurrentIndex CurrentIndex { get { return BaseProperty.Group.CurrentIndex; } }
      public override World World { get { return Container.Block.World; } }
      public override int AllocationSize {
        get {
          if (BaseProperty.Group.Count == 0) return 1;
          else return Container.Block.Count * BaseProperty.Group.Count;
        }
      }
      public override BasePhysicsPropertyValue<S> Normal {
        get { return new PhysicsPropertyValue<S>() { BaseProperty = BaseProperty, 
          Container = new BaseBaseBlockValue() { Block = Container.Block, Index = 0 }, 
          BaseIndex = new Constant<int>(0) }; }
      }
      public override string ToString() { return Container.ToString() + "[" + BaseIndex + "]." + Property.Name; }
      public override int GetHashCode() {
        var code = Container.GetHashCode() + Property.GetHashCode() + BaseIndex.GetHashCode();
        return code;
      }
      public override bool Equals(object obj) {
        if (obj is PhysicsPropertyValue<S>) {
          var obj0 = ((PhysicsPropertyValue<S>)obj);
          var result = obj0.Container.Equals(Container);
          result = result && obj0.BaseIndex.Equals(BaseIndex);
          result = result && obj0.Property == Property;
          return result;
        }
        return base.Equals(obj);
      }
    }
    internal override Expr<S> GetProperty<S>(PhysicsProperty<S> p, IntBl BodyIndex, IntBl SubIndex) {
      return new PhysicsPropertyValue<S>() {
        Container = new BaseBaseBlockValue() { Block = this, Index = BodyIndex },
        BaseIndex = SubIndex, BaseProperty = p
      };
    }
    protected class BaseBody : Body {
      internal IntBl Index0;
      internal BLOCK Block0;
      public IntBl Index { get { return Index0; } }
      public BLOCK Block { get { return Block0; } }

      public Expr<S> GetProperty<S>(PhysicsProperty<S> p) {
        (p.Group == this.Block.BodyProperties).Assert();
        return Block.GetProperty<S>(p, Index, 0);
      }
      public BaseSubBlockFactory<SubBlockT> SubBlock<SubBlockT>(PropertyGroup Id) where SubBlockT : SubBlock<SubBlockT>, new() {
        (Id != null).Assert();
        return new SubBlockFactory<SubBlockT>() { Container = this, Id = Id };
      }
      protected BodyT Relative<BodyT, BodyC>(IntBl Offset)
        where BodyT : Body
        where BodyC : BaseBody, BodyT, new() {
        return new BodyC() { Block0 = Block, Index0 = (Index + Offset).Normalize(Block.Count) };
      }


      public Body this[IntBl Offset] { get { return Relative<Body, BaseBody>(Offset); } }
      public CursorNextPrev<Body> Next { get { return NextX<Body, BaseBody>(); } }
      public CursorNextPrev<Body> Prev { get { return PrevX<Body, BaseBody>(); } }
      protected CursorNextPrev<BodyT> NextX<BodyT, BodyC>()
        where BodyT : Body
        where BodyC : BaseBody, BodyT, new() {
        return NextPrev0<BodyT, BodyC>((a, b, c) => (a + b).NormalizeUp(c));
      }
      protected CursorNextPrev<BodyT> PrevX<BodyT, BodyC>()
        where BodyT : Body
        where BodyC : BaseBody, BodyT, new() {
        return NextPrev0<BodyT, BodyC>((a, b, c) => (a - b).NormalizeDown(c));
      }
      private CursorNextPrev<BodyT> NextPrev0<BodyT, BodyC>(Func<IntBl, IntBl, IntBl, IntBl> F)
        where BodyT : Body
        where BodyC : BaseBody, BodyT, new() {
        return new CursorNextPrev<BodyT>((Offset) => new BodyC() { Block0 = Block, Index0 = F(Index, Offset, Block.Count) });
      }
      public BodyCursor<T> Cursor<T>(PhysicsProperty<T> Property) {
        return new PropertyCursor<T>() { BodyAt = this, BaseProperty = Property };
      }
      private class PropertyCursor<T> : BodyCursor<T> {
        internal PhysicsProperty<T> BaseProperty;
        internal BaseBody BodyAt;
        public Body Body { get { return BodyAt; } }
        public Expr<T> At {
          get { return BodyAt.GetProperty(Property); }
        }
        public PhysicsProperty<T> Property { get { return BaseProperty; } }
        public IntBl Index { get { return BodyAt.Index; } }
        public IntBl Count { get { return BodyAt.Block.Count; } }
        public Expr<T> this[IntBl Offset] {
          get { return BodyAt[Offset].GetProperty(Property); }
        }
        public CursorNextPrev<Expr<T>> Next { get { return new CursorNextPrev<Expr<T>>((i) => BodyAt.Next[i].GetProperty(Property)); } }
        public CursorNextPrev<Expr<T>> Prev { get { return new CursorNextPrev<Expr<T>>((i) => BodyAt.Prev[i].GetProperty(Property)); } }
      }
      protected class SubBlockFactory<SubBlockT> : BaseSubBlockFactory<SubBlockT>
        where SubBlockT : SubBlock<SubBlockT>, new() {
        public BaseBody Container;
        public PropertyGroup Id;
        public int Count { get { return Id.Count; } }
        public SubBlockT this[IntBl index] {
          get {
            var block = new SubBlockT() {
              Id = Id, Index = index,
              Container = new BaseBaseBlockValue() { Block = Container.Block, Index = Container.Index },
            };
            return block;
          }
        }
        public void ForAll(Action<SubBlockT> F) {
          var block = new SubBlockT() {
            Id = Id, Index = Id.CurrentIndex,
            Container = new BaseBaseBlockValue() { Block = Container.Block, Index = Container.Index },
          };
          F(block);
        }
      }
    }

  }
  internal interface BaseBlockDependencyPropertyValue : BaseExpr {
    BaseBlockDependencyPropertyValue BaseNormal { get; }
    PhysicsBlock.BaseBaseBlockValue BaseContainer { get; }
    DependencyProperty BaseWriteProperty { get; }
    int AllocationSize { get; }
    BaseBlockDependencyPropertyValue All { get; }
  }
  internal abstract class BaseBlockDependencyPropertyValue<T> : PropertyValue<T>, BaseBlockDependencyPropertyValue {
    public DependencyProperty ReadProperty;
    public DependencyProperty WriteProperty;

    public DependencyProperty BaseWriteProperty { get { return WriteProperty; } }
    public override string ToString() { return BaseContainer.ToString() + "." + WriteProperty.Name; }

    public abstract PhysicsBlock.BaseBaseBlockValue BaseContainer { get; }
    public abstract BaseBlockDependencyPropertyValue<T> Normal { get; }
    public BaseBlockDependencyPropertyValue BaseNormal { get { return Normal; } }
    public IntBl Index { get { return BaseContainer.Index; } }
    public abstract BaseBlockDependencyPropertyValue All { get; }

    public abstract int AllocationSize { get; } 
  }
  public abstract class ImmediatePhysicsBlock<BLOCK> : PhysicsBlock<BLOCK> where BLOCK : ImmediatePhysicsBlock<BLOCK> {
    private readonly int Count0;
    public ImmediatePhysicsBlock(World World, int Count0) : base(World) {
      this.Count0 = Count0;
    }
    public override int Count { get { return Count0; } }
  }
  public class PlainBlock : ImmediatePhysicsBlock<PlainBlock> {
    public PlainBlock(World World, int Count0) : base(World, Count0) { }

  }
  public interface RetainedPhysicsBlock {
    /// <summary>
    /// Underlying array of dependency objects that are wrapped by this block.
    /// </summary>
    DependencyObject[] BaseUnderlying { get; }
  }
  public interface RetainedPhysicsBlock<T> : RetainedPhysicsBlock where T : DependencyObject {
    T Get(int Index);
  }
  public abstract class PhysicsBlock<T, BLOCK> : PhysicsBlock<BLOCK>, RetainedPhysicsBlock<T>
    where BLOCK : PhysicsBlock<T, BLOCK>
    where T : DependencyObject {
    protected readonly T[] Underlying;
    public PhysicsBlock(World World, T[] Underlying) : base(World) {
      this.Underlying = Underlying;
    }
    public PhysicsBlock(World World, Func<BLOCK, int> CountF, Func<BLOCK, int, T> MakeT)
      : base(World) {
      var Count = CountF((BLOCK)this);
      Underlying = new T[Count];
      for (int i = 0; i < Count; i++)
        Underlying[i] = MakeT((BLOCK)this, i);
    }

    public PhysicsBlock(World World, int Count, Func<int, T> MakeT)
      : this(World, block => Count, (a, b) => MakeT(b)) {
    }
    public T Get(int index) { return Underlying[index]; }

    public DependencyObject[] BaseUnderlying { get { return Underlying; } }
    public override int Count { get { return Underlying.Length; } }

    internal sealed class BlockValue : Expr<T> { 
      internal BaseBlockValue Underlying {
        get { return new BaseBlockValue() { Block = (BLOCK) Block, Index = Index }; }
      }
      public static implicit operator BaseBlockValue(BlockValue v) { return v.Underlying; }
      public static implicit operator BaseBaseBlockValue(BlockValue bv) {
        return new BaseBaseBlockValue() { Block = bv.Block, Index = bv.Index };
      }
      internal PhysicsBlock<T,BLOCK> Block;
      public PhysicsBlock<BLOCK> BaseBlock { get { return Block; } }
      public IntBl Index { get; internal set; }
      public bool IsAll { get { return Index.Underlying == Block.CurrentIndex; } }
      public BlockValue Denormal(int idx) {
        return new BlockValue() {
          Block = Block, Index = idx,
        };
      }
      public override Eval<EVAL>.Info<T> Eval<EVAL>(Eval<EVAL> txt) {
        if (txt is TableEval<EVAL>)
          return ((TableEval<EVAL>)txt).Block<T>(Block.Underlying, Index.Underlying.Eval(txt));
        else if (Index.Underlying is Constant<T>) 
          return new Constant<T>(Block.Underlying[(((Constant<int>)Index.Underlying).Value)]).Eval(txt);
        else if (txt is TranslateEval<EVAL>) {
          var idx = ((TranslateEval<EVAL>)txt).Translate(Index.Underlying);

          return new TranslateEval<EVAL>.MyInfo<T>() { Value = new BlockValue() { Block = Block, Index = idx } };
        }

        throw new NotSupportedException(); // cannot evaluate.
      }
      public override PropertyValue<S> Property<S>(DependencyProperty ReadProperty, DependencyProperty WriteProperty) {
        return new BlockDependencyPropertyValue<S>() { // because we could be in a block. 
          ReadProperty = ReadProperty, WriteProperty = WriteProperty, Container = this,
        };
      }
      public int AllocationSize { get { return Block.Count; } }
      public CurrentIndex CurrentIndex { get { return Block.CurrentIndex; } }
      public World World { get { return Block.World; } }

      public BlockValue Normal {
        get { return new BlockValue() { Index = new Constant<int>(0), Block = Block }; }
      }
      public override string ToString() { return Block.ToString() + "[" + Index + "]"; }
      public override int GetHashCode() {
        return Block.GetHashCode() + Index.Underlying.GetHashCode();
      }
      public override bool Equals(object obj) {
        if (obj is BlockValue) {
          var obj0 = ((BlockValue)obj);
          return obj0.Block == Block && obj0.Index.Underlying.Equals(Index.Underlying);
        }
        return base.Equals(obj);
      }
    }
    internal class BlockDependencyPropertyValue<S> : BaseBlockDependencyPropertyValue<S>, BindableExpr<S> {
      internal BlockValue Container;
      public override BaseBaseBlockValue BaseContainer {
        get { return Container; }
      }
      public override BaseBlockDependencyPropertyValue<S> Normal {
        get { return new BlockDependencyPropertyValue<S>() { Container = Container.Normal, ReadProperty = ReadProperty, WriteProperty = WriteProperty }; }
      }
      public override int AllocationSize {
        get { return Container.BaseBlock.Count; }
      }
      public override BaseBlockDependencyPropertyValue All {
        get {
          (Container.Index.Underlying.Equals(new Constant<int>(0))).Assert();
          return new BlockDependencyPropertyValue<S>() {
            ReadProperty = ReadProperty, WriteProperty = WriteProperty,
            Container = new BlockValue() { Block = Container.Block, Index = Container.Block.CurrentIndex },
          };
        }
      }
      public override int GetHashCode() {
        return Container.GetHashCode() + ReadProperty.GetHashCode() + WriteProperty.GetHashCode();
      }
      public override bool Equals(object obj) {
        if (obj is BlockDependencyPropertyValue<S>) {
          var obj0 = ((BlockDependencyPropertyValue<S>)obj);
          return obj0.Container.Equals(Container) && obj0.ReadProperty == ReadProperty && obj0.WriteProperty == WriteProperty;
        }
        return base.Equals(obj);
      }
      public override Eval<EVAL>.Info<S> Eval<EVAL>(Eval<EVAL> txt) {
        if (txt is PhysicsEval<EVAL>) {
          return ((PhysicsEval<EVAL>)txt).Physics.Eval(this);
          /*
        } else if (txt is DependencyPropertyEval2<EVAL>) {
          Eval<EVAL>.Info<T> info = this.Container.Eval(txt);
          var txt0 = (DependencyPropertyEval2<EVAL>)txt;
          return txt0.PropertyValue<T, S>(info, this.ReadProperty);
           */
        } else if (txt is DependencyPropertyEval<EVAL>) {
          var dp = new DependencyPropertyValue<T,S>() { TargetValue = this.Container, ReadProperty = ReadProperty, WriteProperty = WriteProperty };
          return dp.Eval(txt);
        } else if (txt is TranslateEval<EVAL>) {
          // the dependency property is not important.
          var containerB = (BlockValue) ((TranslateEval<EVAL>.MyInfo<T>)Container.Eval(txt)).Value;
          var value = new BlockDependencyPropertyValue<S>() { Container = containerB, WriteProperty = WriteProperty, ReadProperty = ReadProperty };
          return new TranslateEval<EVAL>.MyInfo<S>() { Value = value };
        }
        throw new NotImplementedException();
      }
      public bool BindWith(Expr<S> value) {
        if (this.Container.Index.Underlying is CurrentIndex) {
          var idx = (CurrentIndex)this.Container.Index.Underlying;
          bool ret = true;
          Expr<S>.ProcessAll(this, value, idx, (lhs, rhs) => ret = ((BindableExpr<S>)lhs).BindWith(rhs) && ret);
          return ret;
        } else {
          var dp = new DependencyPropertyValue<T,S>() { TargetValue = this.Container, ReadProperty = ReadProperty, WriteProperty = WriteProperty };
          return dp.BindWith(value);
        }
      }
    }
    public new interface Body : PhysicsBlock<BLOCK>.Body {
      new Body this[IntBl offset] { get; }
      new CursorNextPrev<Body> Next { get; }
      new CursorNextPrev<Body> Prev { get; }
      Expr<T> At { get; }
    }
    protected new class BaseBody : PhysicsBlock<BLOCK>.BaseBody, Body {
      public new Body this[IntBl Offset] { get { return Relative<Body, BaseBody>(Offset); } }
      public new CursorNextPrev<Body> Next { get { return NextX<Body, BaseBody>(); } }
      public new CursorNextPrev<Body> Prev { get { return PrevX<Body, BaseBody>(); } }
      public Expr<T> At { get { return new BlockValue() { Index = Index, Block = Block }; } }
    }
    public new Body this[IntBl idx] { get { return new BaseBody() { Block0 = (BLOCK)this, Index0 = idx }; } }
    public void ForAll(Action<Body> F) { F(new BaseBody() { Block0 = (BLOCK)this, Index0 = CurrentIndex }); }

  }
  /// <summary>
  /// A physics block of bodies that wrap a list of underlying elements.
  /// </summary>
  /// <typeparam name="T">Stripped type of elements (e.g., Slider).</typeparam>
  /// <typeparam name="BRAND">Bling type of elements (e.g., SliderBl).</typeparam>
  /// <typeparam name="BLOCK">The block's self type (useful in definigng extension methods).</typeparam>
  public abstract class PhysicsBlock<T,BRAND, BLOCK> : PhysicsBlock<T,BLOCK> where BRAND : Brand<T,BRAND> where BLOCK : PhysicsBlock<T,BRAND,BLOCK> where T : DependencyObject {
    /// <param name="World">Physics world block belong's to.</param>
    /// <param name="Underlying">Array of existing elements wrapped by the block.</param>
    public PhysicsBlock(World World, T[] Underlying) : base(World, Underlying) { }
    /// <param name="World">Physics world block belong's to.</param>
    /// <param name="Count">Number of elements to create.</param>
    /// <param name="MakeT">Factory function for creating elements.</param>
    public PhysicsBlock(World World, int Count, Func<int, T> MakeT) : base(World, Count, MakeT) { }
    public PhysicsBlock(World World, Func<BLOCK, int> CountF, Func<BLOCK, int, T> MakeT) : base(World, CountF, MakeT) { }


    public new interface Body : PhysicsBlock<T,BLOCK>.Body {
      new Body this[IntBl offset] { get; }
      new CursorNextPrev<Body> Next { get; }
      new CursorNextPrev<Body> Prev { get; }
      new BRAND At { get; }
    }
    protected new class BaseBody : PhysicsBlock<T,BLOCK>.BaseBody, Body {
      public new Body this[IntBl Offset] { get { return Relative<Body, BaseBody>(Offset); } }
      public new CursorNextPrev<Body> Next { get { return NextX<Body, BaseBody>(); } }
      public new CursorNextPrev<Body> Prev { get { return PrevX<Body, BaseBody>(); } }
      public new BRAND At { get { return Brand<T,BRAND>.ToBrand(new BlockValue() { Index = Index, Block = Block }); } }
    }
    public new Body this[IntBl idx] { get { return new BaseBody() { Block0 = (BLOCK)this, Index0 = idx }; } }
    public void ForAll(Action<Body> F) { F(new BaseBody() { Block0 = (BLOCK)this, Index0 = CurrentIndex }); }
  }

  public class PlainBlock<T> : PhysicsBlock<T, PlainBlock<T>> where T : DependencyObject {
    public PlainBlock(World World, T[] Underlying) : base(World, Underlying) { }
    public PlainBlock(World World, int Count, Func<int, T> MakeT) : base(World, Count, MakeT) { }
  }
  /// <summary>
  /// A basic physics block with a non-unique self parameter binding. 
  /// </summary>
  /// <typeparam name="T">Type of block elements.</typeparam>
  /// <typeparam name="BRAND">Corresponding "Bl" type for T.</typeparam>
  public class PlainBlock<T, BRAND> : PhysicsBlock<T, BRAND, PlainBlock<T, BRAND>>
    where T : DependencyObject
    where BRAND : Brand<T, BRAND> {
    /// <param name="World">Physics world block belong's to.</param>
    /// <param name="Underlying">Array of existing elements wrapped by the block.</param>
    public PlainBlock(World World, T[] Underlying) : base(World, Underlying) { }
    /// <param name="World">Physics world block belong's to.</param>
    /// <param name="Count">Number of elements to create.</param>
    /// <param name="MakeT">Factory function for creating elements.</param>
    public PlainBlock(World World, int Count, Func<int, T> MakeT) : base(World, Count, MakeT) { }
  }
 

  public class PositionBlock<T, BRAND> : PhysicsBlock<T, BRAND, PositionBlock<T, BRAND>>, Position2DBody.Is<PositionBlock<T,BRAND>>
    where T : DependencyObject
    where BRAND : Brand<T, BRAND> {
    private void InitE() {
      new Position2DBody.Impl<PositionBlock<T, BRAND>>(this);
    }
    public PositionBlock(World World, T[] Underlying) : base(World, Underlying) { InitE(); }
    public PositionBlock(World World, int Count, Func<int, T> MakeT) : base(World, Count, MakeT) { InitE(); }
  }
  public class Position3DBlock<T, BRAND> : PhysicsBlock<T, BRAND, Position3DBlock<T, BRAND>>, Position3DBody.Is<Position3DBlock<T, BRAND>>
    where T : DependencyObject
    where BRAND : Brand<T, BRAND> {
    private void InitE() {
      new Position3DBody.Impl<Position3DBlock<T, BRAND>>(this);
    }
    public Position3DBlock(World World, T[] Underlying) : base(World, Underlying) { InitE(); }
    public Position3DBlock(World World, int Count, Func<int, T> MakeT) : base(World, Count, MakeT) { InitE(); }
  }


  public static partial class PhysicsExtensions {
    public static void TwoWay<T,BRAND>(this Cursor<Expr<T>> P, IntBl N, DoubleBl Strength, Func<BRAND, BRAND> F) where BRAND : CoreBl<T,BRAND> {
      CoreBl<T,BRAND>.ToBrand(P.At).Relax[Strength * .5, P.Index >= N] = F(CoreBl<T,BRAND>.ToBrand(P.Prev[N]));
      CoreBl<T,BRAND>.ToBrand(P.At).Relax[Strength * .5, P.Index < P.Count - N] = F(CoreBl<T,BRAND>.ToBrand(P.Next[N]));
    }
  }
  [Obsolete]
  public class GridManager2 {
    public IntBl ColumnCount = 10;
    public IntBl RowCount = 10;
    public PointBl CellSize = new PointBl(10d, 10d);
    public PointBl LeftTop = new PointBl(0, 0);
    public PointBl Size = new PointBl(100, 100);

    public PointBl Cell(Cursor<Expr<Point>> body, IntBl X, IntBl Y) {
      IntBl Column = body.Index % ColumnCount;
      IntBl Row = body.Index / ColumnCount;
      //body.Next[+1];
      var Target = body[X + Y * ColumnCount];
      PointBl P = (Target);

      IntBl Column0 = Column + X;
      DoubleBl Dx = body[X].Bl().X;
      Dx = (Column0 < 0).Condition(LeftTop.X + (Column0 + 1) * CellSize.X, Dx);
      Dx = (Column0 >= ColumnCount).Condition(LeftTop.X + Size.X + (Column0 - ColumnCount) * CellSize.Y, Dx);

      IntBl Row0 = Row + Y;
      DoubleBl Dy = body[Y * ColumnCount].Bl().Y;
      Dy = (Row0 < 0).Condition(LeftTop.Y + (Row0 + 1) * CellSize.Y, Dy);
      Dy = (Row0 >= RowCount).Condition(LeftTop.Y + Size.Y + (Row0 - RowCount) * CellSize.Y, Dy);

      P = (Column0 >= 0 & Column0 < ColumnCount & Row0 >= 0 & Row0 < RowCount).Condition(P, new PointBl(Dx, Dy));

      return P;
    }
    public Point3DBl Cell(Cursor<Expr<Point3D>> body, IntBl X, IntBl Y) {
      IntBl Column = body.Index % ColumnCount;
      IntBl Row = body.Index / ColumnCount;
      //body.Next[+1];
      var Target = body[X + Y * ColumnCount];
      Point3DBl P = (Target);

      IntBl Column0 = Column + X;
      DoubleBl Dx = body[X].Bl().X;
      Dx = (Column0 < 0).Condition(LeftTop.X + (Column0 + 1) * CellSize.X, Dx);
      Dx = (Column0 >= ColumnCount).Condition(LeftTop.X + Size.X + (Column0 - ColumnCount) * CellSize.Y, Dx);

      IntBl Row0 = Row + Y;
      DoubleBl Dy = body[Y * ColumnCount].Bl().Y;
      Dy = (Row0 < 0).Condition(LeftTop.Y + (Row0 + 1) * CellSize.Y, Dy);
      Dy = (Row0 >= RowCount).Condition(LeftTop.Y + Size.Y + (Row0 - RowCount) * CellSize.Y, Dy);

      P = (Column0 >= 0 & Column0 < ColumnCount & Row0 >= 0 & Row0 < RowCount).Condition(P, new Point3DBl(Dx, Dy, 0));
      return P;
    }
  }
  /// <summary>
  /// For blocks with 2D position properties.
  /// </summary>
  public static class Position2DBody {
    public interface Is<BLOCK> : PositionBody<Point, PointBl>.Is<BLOCK> where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> { }
    public class Impl<BLOCK> : PositionBody<Point, PointBl>.Impl<BLOCK> where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      public Impl(BLOCK block) : base(block) { }
    }

    public static PointBl Position<BLOCK>(this PhysicsBlock<BLOCK>.Body body)
      where BLOCK : PhysicsBlock<BLOCK>, PositionBody<Point,PointBl>.Is<BLOCK> {
      return PositionBody<Point, PointBl>.Position(body);
    }
    public static Cursor<Expr<Point>> CursorPosition<BLOCK>(this PhysicsBlock<BLOCK>.Body body)
      where BLOCK : PhysicsBlock<BLOCK>, PositionBody<Point, PointBl>.Is<BLOCK> {
      return PositionBody<Point, PointBl>.CursorPosition(body);
    }
    public static Array1D<Point> PositionArray<BLOCK>(this PhysicsBlock<BLOCK> block)
      where BLOCK : PhysicsBlock<BLOCK>, PositionBody<Point, PointBl>.Is<BLOCK> {
      return PositionBody<Point, PointBl>.PositionArray(block);
    }
  }
  /// <summary>
  /// For blocks with 3D position properties.
  /// </summary>
  public static class Position3DBody {
    public interface Is<BLOCK> : PositionBody<Point3D, Point3DBl>.Is<BLOCK> where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> { }
    public class Impl<BLOCK> : PositionBody<Point3D, Point3DBl>.Impl<BLOCK> where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      public Impl(BLOCK block) : base(block) {
        new Point3DBl(0, 0, 0);
        Point3DBl.ToBrand(new Point3D(0, 0, 0));
      
      }
    }
    /// <summary>
    /// 3D position of this body.
    /// </summary>
    public static Point3DBl Position3D<BLOCK>(this PhysicsBlock<BLOCK>.Body body)
      where BLOCK : PhysicsBlock<BLOCK>, PositionBody<Point3D, Point3DBl>.Is<BLOCK> {
      return PositionBody<Point3D, Point3DBl>.Position(body);
    }
    /// <summary>
    /// 3D position cursor of this body.
    /// </summary>
    public static PhysicsBlock<BLOCK>.BodyCursor<Point3D> CursorPosition3D<BLOCK>(this PhysicsBlock<BLOCK>.Body body)
      where BLOCK : PhysicsBlock<BLOCK>, PositionBody<Point3D, Point3DBl>.Is<BLOCK> {
      return PositionBody<Point3D, Point3DBl>.CursorPosition(body);
    }
    /// <summary>
    /// 3D positions of this block as an array.
    /// </summary>
    public static Array1D<Point3D> Position3DArray<BLOCK>(this PhysicsBlock<BLOCK> block)
      where BLOCK : PhysicsBlock<BLOCK>, PositionBody<Point3D, Point3DBl>.Is<BLOCK> {
      return PositionBody<Point3D, Point3DBl>.PositionArray(block);
    }
  }
  /// <summary>
  /// For blocks that form grid-like meshes. 
  /// </summary>
  public static class MeshBody {
    public static Impl<BLOCK> MeshBodyE<BLOCK>(this PhysicsBlock<BLOCK> block)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, PositionBody.Is<BLOCK> {
      return block.Extension<Impl<BLOCK>>();
    }
    /// <summary>
    /// Number of columns in mesh.
    /// </summary>
    public static int ColumnCount<BLOCK>(this PhysicsBlock<BLOCK> block)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, PositionBody.Is<BLOCK> {
      return block.MeshBodyE().ColumnCount;
    }
    /// <summary>
    /// Number of rows in mesh.
    /// </summary>
    public static int RowCount<BLOCK>(this PhysicsBlock<BLOCK> block)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, PositionBody.Is<BLOCK> {
      return block.MeshBodyE().RowCount;
    }
    /// <summary>
    /// Get body at specified Column, Row index in mesh.
    /// </summary>
    /// <param name="X">Column offset.</param>
    /// <param name="Y">Row offset.</param>
    public static PhysicsBlock<BLOCK>.Body Get<BLOCK>(this PhysicsBlock<BLOCK> block, IntBl X, IntBl Y)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, PositionBody.Is<BLOCK> {
      var idx = X + Y * block.MeshBodyE().ColumnCount;
      return block[idx.Normalize(block.Count)];
    }
    /// <summary>
    /// Column index of body.
    /// </summary>
    public static IntBl Column<BLOCK>(this PhysicsBlock<BLOCK>.Body body)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, PositionBody.Is<BLOCK> {
      return body.Index % body.Block.ColumnCount();
    }
    /// <summary>
    /// Row index of body.
    /// </summary>
    public static IntBl Row<BLOCK>(this PhysicsBlock<BLOCK>.Body body)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, PositionBody.Is<BLOCK> {
      return body.Index / body.Block.ColumnCount();
    }
    public static BoolBl IsFirstRow<BLOCK>(this PhysicsBlock<BLOCK>.Body body)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, PositionBody.Is<BLOCK> {
      return body.Row() == 0;
    }
    public static BoolBl IsFirstColumn<BLOCK>(this PhysicsBlock<BLOCK>.Body body)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, PositionBody.Is<BLOCK> {
      return body.Column() == 0;
    }
    public static BoolBl IsLastRow<BLOCK>(this PhysicsBlock<BLOCK>.Body body)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, PositionBody.Is<BLOCK> {
      return body.Row() == body.Block.RowCount() - 1;
    }
    public static BoolBl IsLastColumn<BLOCK>(this PhysicsBlock<BLOCK>.Body body)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, PositionBody.Is<BLOCK> {
      return body.Column() == body.Block.ColumnCount() - 1;
    }
    public static Expr<S> Access<BLOCK, S>(this PhysicsBlock<BLOCK>.BodyCursor<S> cursor, IntBl X, IntBl Y)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, PositionBody.Is<BLOCK> {
      IntBl Row = cursor.Body.Row();
      IntBl Column = cursor.Body.Column();
      Expr<S> Target = cursor[X + Y * cursor.Body.Block.ColumnCount()];
      // what to do if out of bounds?
      return Target;
    }
    /// <summary>
    /// Compute spring point for cursor property at specified X, Y offset.
    /// </summary>
    /// <param name="cursor">Location of current property as a cursor.</param>
    /// <param name="X">Horizontal X offset in grid of property to spring against.</param>
    /// <param name="Y">Vertical Y offset in grid of property to spring against.</param>
    /// <returns>Spring location of current property in grid with respect to spring constraint.</returns>
    public static Point3DBl Spring<BLOCK>(this PhysicsBlock<BLOCK>.BodyCursor<Point3D> cursor, IntBl X, IntBl Y)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, PositionBody.Is<BLOCK> {
      var p = cursor.Access(X, Y);
      PointBl CellSize = cursor.Body.Block.MeshBodyE().CellSize;
      return cursor.At.Bl().Spring(p, (CellSize * (new PointBl(X, Y))).Length);
    }
    /// <summary>
    /// Compute spring point for cursor property at specified X, Y offset.
    /// </summary>
    /// <param name="cursor">Location of current property as a cursor.</param>
    /// <param name="X">Horizontal X offset in grid of property to spring against.</param>
    /// <param name="Y">Vertical Y offset in grid of property to spring against.</param>
    /// <returns>Spring location of current property in grid with respect to spring constraint.</returns>
    public static PointBl Spring<BLOCK>(this PhysicsBlock<BLOCK>.BodyCursor<Point> cursor, IntBl X, IntBl Y)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, PositionBody.Is<BLOCK> {
      var p = cursor.Access(X, Y);
      PointBl CellSize = cursor.Body.Block.MeshBodyE().CellSize;
      return cursor.At.Bl().Spring(p, (CellSize * (new PointBl(X, Y))).Length);
    }
    /// <summary>
    /// Accesss value for neighbor of property at X, Y offset. 
    /// </summary>
    /// <param name="cursor">Location of current property as a cursor.</param>
    /// <param name="X">Horizontal X offset of property to access.</param>
    /// <param name="Y">Vertical Y offset of property to access.</param>
    /// <returns></returns>
    public static Point3DBl Access<BLOCK>(this PhysicsBlock<BLOCK>.BodyCursor<Point3D> cursor, IntBl X, IntBl Y)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, PositionBody.Is<BLOCK> {
      IntBl Row = cursor.Body.Row();
      IntBl Column = cursor.Body.Column();
      int ColumnCount = cursor.Body.Block.ColumnCount();
      int RowCount = cursor.Body.Block.RowCount();

      Point3DBl Target = cursor[X + Y * ColumnCount];

      IntBl Column0 = Column + X;
      IntBl Row0 = Row + Y;

      PointBl LeftTop = cursor.Body.Block.MeshBodyE().LeftTop;
      PointBl Size = cursor.Body.Block.MeshBodyE().Size;
      PointBl CellSize = cursor.Body.Block.MeshBodyE().CellSize;

      DoubleBl Dx = cursor[X].Bl().X;
      Dx = (Column0 < 0).Condition(LeftTop.X + Column0 * CellSize.X, Dx);
      Dx = (Column0 >= cursor.Body.Block.ColumnCount()).Condition(
        LeftTop.X + Size.X + (Column0 - ColumnCount + 1) * CellSize.X, Dx);

      DoubleBl Dy = cursor[Y * ColumnCount].Bl().Y;
      Dy = (Row0 < 0).Condition(LeftTop.Y + (Row0) * CellSize.Y, Dy);
      Dy = (Row0 >= RowCount).Condition(
        LeftTop.Y + Size.Y + (Row0 - RowCount + 1) * CellSize.Y, Dy);


      Target = (Column0 >= 0 & Column0 < cursor.Body.Block.ColumnCount() &
                   Row0 >= 0 & Row0    < cursor.Body.Block.RowCount()).Condition(Target, new Point3DBl(Dx, Dy, 0));

      return Target;
    }
    /// <summary>
    /// Accesss value for neighbor of property at X, Y offset. 
    /// </summary>
    /// <param name="cursor">Location of current property as a cursor.</param>
    /// <param name="X">Horizontal X offset of property to access.</param>
    /// <param name="Y">Vertical Y offset of property to access.</param>
    /// <returns></returns>
    public static PointBl Access<BLOCK>(this PhysicsBlock<BLOCK>.BodyCursor<Point> cursor, IntBl X, IntBl Y)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, PositionBody.Is<BLOCK> {
      IntBl Row = cursor.Body.Row();
      IntBl Column = cursor.Body.Column();
      int ColumnCount = cursor.Body.Block.ColumnCount();
      int RowCount = cursor.Body.Block.RowCount();

      PointBl Target = cursor[X + Y * ColumnCount];

      IntBl Column0 = Column + X;
      IntBl Row0 = Row + Y;

      PointBl LeftTop = cursor.Body.Block.MeshBodyE().LeftTop;
      PointBl Size = cursor.Body.Block.MeshBodyE().Size;
      PointBl CellSize = cursor.Body.Block.MeshBodyE().CellSize;

      DoubleBl Dx = cursor[X].Bl().X;
      Dx = (Column0 < 0).Condition(LeftTop.X + Column0 * CellSize.X, Dx);
      Dx = (Column0 >= cursor.Body.Block.ColumnCount()).Condition(LeftTop.X + Size.X + (Column0 - ColumnCount + 1) * CellSize.Y, Dx);

      DoubleBl Dy = cursor[Y * ColumnCount].Bl().Y;
      Dy = (Row0 < 0).Condition(LeftTop.Y + (Row0) * CellSize.Y, Dy);
      Dy = (Row0 >= RowCount).Condition(LeftTop.Y + Size.Y + (Row0 - RowCount + 1) * CellSize.Y, Dy);


      Target = (Column0 >= 0 & Column0 < cursor.Body.Block.ColumnCount() &
                   Row0 >= 0 & Row0 < cursor.Body.Block.RowCount()).Condition(Target, new PointBl(Dx, Dy));

      return Target;
    }
    /// <summary>
    /// Extending blocks must implement this interface.
    /// </summary>
    public interface Is<BLOCK> : HasBlockExtension<BLOCK, Impl<BLOCK>> where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, PositionBody.Is<BLOCK> { }
    /// <summary>
    /// Extending blocks must instantiate this class.
    /// </summary>
    public class Impl<BLOCK> : BlockExtension<Impl<BLOCK>, BLOCK>
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, PositionBody.Is<BLOCK> {
      public readonly int ColumnCount;
      public readonly int RowCount;
      public PointBl LeftTop = new PointBl(0, 0);
      public PointBl Size = new PointBl(1, 1);
      public PointBl CellSize {
        get {
          return Size / new PointBl(ColumnCount - 1, RowCount - 1) * CellSizeMod;
        }
      }
      public PointBl CellSizeMod {
        private get;
        set;
      }

      public Impl(BLOCK block, int ColumnCount, int RowCount) : base(block) {
        (ColumnCount > 1).Assert();
        (RowCount > 1).Assert();
        this.ColumnCount = ColumnCount; this.RowCount = RowCount;
        (block.Count == ColumnCount * RowCount).Assert();
        CellSizeMod = new PointBl(1, 1);
      }
      protected internal override void DoInit(BLOCK block) {}
    }
  }

  public static class PositionBody {
    public static Impl<BLOCK> PositionBodyE<BLOCK>(this PhysicsBlock<BLOCK> block)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      return block.Extension<Impl<BLOCK>>();
    }
    // marker
    //public interface Is<BLOCK> where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> { }
    public interface Is<BLOCK> : HasBlockExtension<BLOCK, Impl<BLOCK>> where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> { }
    public abstract class Impl<BLOCK> : BlockExtension<Impl<BLOCK>, BLOCK>
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      public abstract BasePointBl PositionFor(PhysicsBlock<BLOCK>.Body body);
      public abstract Array1D<Point3D> PositionArray(PhysicsBlock<BLOCK> block);

      public abstract Type TypeOfPoint { get; }

      public Impl(BLOCK block) : base(block) { }
    }
  }

  public static class PositionBody<P,POINT> where POINT : Brand<P,POINT>, PointBl<P,POINT> {
    public static Impl<BLOCK> PositionBodyE<BLOCK>(PhysicsBlock<BLOCK> block)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      return (Impl<BLOCK>) block.Extension<PositionBody.Impl<BLOCK>>();
    }

    /// <summary>
    /// Position for this body.
    /// </summary>
    public static POINT Position<BLOCK>(PhysicsBlock<BLOCK>.Body body) 
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      BLOCK block = body.Block;
      return Brand<P,POINT>.ToBrand(body.GetProperty(PositionBodyE(body.Block).PositionProperty));
    }
    /// <summary>
    /// Cursor position for this body.
    /// </summary>
    public static PhysicsBlock<BLOCK>.BodyCursor<P> CursorPosition<BLOCK>(PhysicsBlock<BLOCK>.Body body) where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      return body.Cursor(PositionBodyE(body.Block).PositionProperty);
    }
    public static Array1D<P> PositionArray<BLOCK>(PhysicsBlock<BLOCK> block) where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      return new Array1D<P>(block.Count, i => Position(block[i.Normalize(block.Count)]));
    }

    public interface Is<BLOCK> : PositionBody.Is<BLOCK> where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> { }
    public class Impl<BLOCK> : PositionBody.Impl<BLOCK>
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      internal readonly PhysicsProperty<P> PositionProperty;

      public override BasePointBl PositionFor(PhysicsBlock<BLOCK>.Body body) {
        return Brand<P,POINT>.ToBrand(body.GetProperty(PositionProperty));
      }
      public override Array1D<Point3D> PositionArray(PhysicsBlock<BLOCK> block) {
        Array1D<P> array = PositionBody<P,POINT>.PositionArray<BLOCK>(block);
        if (typeof(P) == typeof(Point3D)) {
          return (Array1D<Point3D>)(object)array;
        }
        if (typeof(P) == typeof(Point)) {
          var array0 = (Array1D<Point>)(object)array;
          return array0.Map<Point3D>(p => new Point3DBl(p.Bl(), 0));
        }
        throw new NotSupportedException();
      }


      public override Type TypeOfPoint {
        get { return typeof(P); }
      }
      public Impl(BLOCK block) : base(block) {
        PositionProperty = block.NewBodyProperty<P>("Position");
      }
      protected internal override void DoInit(BLOCK block) {
      }
    }
  }

  /// <summary>
  /// Adds particles to the bodies of an extending block.
  /// </summary>
  public static class ParticleBody {
    /// <summary>
    /// A block extends this if they implement the containing extension.
    /// </summary>
    public interface Is<BLOCK> : HasBlockExtension<BLOCK, Impl<BLOCK>> where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> { }
    /// <summary>
    /// State for containing extension.
    /// </summary>
    public class Impl<BLOCK> : BlockExtension<Impl<BLOCK>, BLOCK> where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      private static int ParticlesCount0 = 4;
      /// <summary>
      /// Number of particles. Must be set before extension is instantiated on a block. 
      /// </summary>
      public static int ParticlesCount {
        get {
          TooLate = true;
          return ParticlesCount0; 
        }
        set {
          if (TooLate) throw new Exception("Already used to create block");
          ParticlesCount0 = value; 
        }
      }
      private static bool TooLate = false;
      /// <summary>
      /// Loss value to use in verlet step. Must set before init.
      /// </summary>
      public DoubleBl Loss = 0.02;
      public Impl(BLOCK block) : base(block) {
        ParticleProperties = new PropertyGroup(block, "Particles", ParticlesCount);
        PositionProperty = ParticleProperties.NewProperty<Point>("Position");
      }

      protected internal override void DoInit(BLOCK block) {
        block.ForAll(body => {
          body.Particles().ForAll(particle => {
            particle.Position.Step = (at, old) => at.VerletStep(Loss, old);
          });
        });
      }
      internal readonly PropertyGroup ParticleProperties;
      internal readonly PhysicsProperty<Point> PositionProperty;

      /// <summary>
      /// A sub-block that represents a body's particles. 
      /// </summary>
      public class Particle : PhysicsBlock.SubBlock<Particle> {
        public Particle() { }
        /// <summary>
        /// Physical position of particle. 
        /// </summary>
        public PointBl Position {
          get {
            return this.Property<Point>(((BLOCK) this.Container.Block).Extension<Impl<BLOCK>>().PositionProperty); 
          }
          set { Position.Bind = value; }
        }
        public static implicit operator PointBl(Particle p) { return p.Position; }
      }
    }
    /// <summary>
    /// Access the particle body extension for this block.
    /// </summary>
    public static Impl<BLOCK> ParticleBodyE<BLOCK>(this PhysicsBlock<BLOCK> block) where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      return block.Extension<Impl<BLOCK>>();
    }
    public static void MakeParticleBodyE<BLOCK>(this PhysicsBlock<BLOCK> block) where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      new Impl<BLOCK>((BLOCK)block);
    }

    /// <summary>
    /// Access this body's group of particles.
    /// </summary>
    public static PhysicsBlock<BLOCK>.BaseSubBlockFactory<Impl<BLOCK>.Particle> 
      Particles<BLOCK>(this PhysicsBlock<BLOCK>.Body body) where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      return body.SubBlock<Impl<BLOCK>.Particle>(
        body.Block.ParticleBodyE().ParticleProperties);
    }
    /// <summary>
    /// Access a particle of this body.
    /// </summary>
    public static Impl<BLOCK>.Particle
      Particles<BLOCK>(this PhysicsBlock<BLOCK>.Body body, IntBl idx) where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      return body.Particles()[idx];
    }
    /// <summary>
    /// Bounding box for this body.
    /// </summary>
    public static Point4DBl AABB<BLOCK>(this PhysicsBlock<BLOCK>.Body body) where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      PointBl leftTop = body.Particles()[0].Position;
      PointBl rightBot = leftTop;
      for (int i = 1; i < body.Block.ParticleCount(); i++) {
        leftTop =   leftTop.Min(body.Particles()[i].Position);
        rightBot = rightBot.Max(body.Particles()[i].Position);
      }
      return new Point4DBl(leftTop, rightBot - leftTop);
    }

    public static void Pin<BLOCK>(this PhysicsBlock<BLOCK> block, 
      PointBl Local, Func<PhysicsBlock<BLOCK>.Body,PointBl> Global, 
      Func<PhysicsBlock<BLOCK>.Body,BoolBl> Guard, DoubleBl Strength, Func<PhysicsBlock<BLOCK>.Body,DoubleBl> Scale, params PointBl[] LocalShapePoints)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      //RadianAngleBl[] Angles00 = new RadianAngleBl[block.ParticleCount()];
      DoubleBl[] Radii00 = new DoubleBl[block.ParticleCount()];
      var sp = LocalShapePoints;
      for (int i = 0; i < block.ParticleCount(); i++) {
        var v = ((sp[i]) - Local);
        //Angles00[i] = v.Angle.Normalize;
        Radii00[i] = v.Length;
      }
      block.ForAll(body => {
        var g = Global(body);
        body.Particles().ForAll(p => {
          p.Position.Relax[Strength, Guard(body)] = p.Position.Spring(g, Radii00.Table(p.Index) * Scale(body));
        });
      });
    }

    /// <summary>
    /// Computed center of this body
    /// </summary>
    public static PointBl ComputedCenter<BLOCK>(this PhysicsBlock<BLOCK>.Body body, Func<int,DoubleBl> ParticleCenterWeight) where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      PointBl ret = new PointBl(0, 0);
      DoubleBl TotalWeight = 0d;

      for (int i = 0; i < body.Block.ParticleCount(); i++) {
        var Weight = ParticleCenterWeight(i); // (body.Particles()[i]);
        TotalWeight += Weight;
        ret += (body.Particles()[i].Position * Weight);
      }
      return (TotalWeight == 0d).Condition(new PointBl(0,0), ret / TotalWeight);
    }


    /// <summary>
    /// Number of particles per body.
    /// </summary>
    public static int ParticleCount<BLOCK>(this PhysicsBlock<BLOCK> block) where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      return Impl<BLOCK>.ParticlesCount;
    }
  }
  public static class RigidBody {
    public interface Is<BLOCK> : HasBlockExtension<BLOCK, Impl<BLOCK>> where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> { }
    public class Impl<BLOCK> : BlockExtension<Impl<BLOCK>, BLOCK> where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      public Impl(BLOCK block) : base(block) {
        RotationProperty = block.NewBodyProperty<double>("Rotation");
        CenterProperty = block.NewBodyProperty<Point>("Center");
        ScaleProperty = block.NewBodyProperty<double>("Scale");
      }
      internal readonly PhysicsProperty<double> RotationProperty;
      internal readonly PhysicsProperty<Point> CenterProperty;
      internal readonly PhysicsProperty<double> ScaleProperty;

      protected internal override void DoInit(BLOCK block) {
        block.ForAll(body => {
          body.Scale().Init = 1d;
        });
      }
    }

    public static Impl<BLOCK> RigidBodyE<BLOCK>(this PhysicsBlock<BLOCK> block)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      return block.Extension<Impl<BLOCK>>();
    }
    /// <summary>
    /// Access the computed rotation of this body. 
    /// </summary>
    public static RadianAngleBl Rotation<BLOCK>(this PhysicsBlock<BLOCK>.Body body)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      DoubleBl d = body.GetProperty(body.Block.RigidBodyE().RotationProperty);
      return d.ToRadians();
    }
    /// <summary>
    /// Access the computed scale of this body. 
    /// </summary>
    public static DoubleBl Scale<BLOCK>(this PhysicsBlock<BLOCK>.Body body)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      return body.GetProperty(body.Block.RigidBodyE().ScaleProperty);
    }
    /// <summary>
    /// Access the computed center of this body. 
    /// </summary>
    public static PointBl Center<BLOCK>(this PhysicsBlock<BLOCK>.Body body)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK> {
      return body.GetProperty(body.Block.RigidBodyE().CenterProperty);
    }
  }

  /// <summary>
  /// Extends a block center and rotation computations, along with constraints to make particles match this shape. 
  /// </summary>
  public static class ShapeBody {
    /// <summary>
    /// A block extends this if they implement the containing extension.
    /// </summary>
    public interface Is<BLOCK> : HasBlockExtension<BLOCK, Impl<BLOCK>> 
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, ParticleBody.Is<BLOCK>, RigidBody.Is<BLOCK> { }
    /// <summary>
    /// State for containing extension.
    /// </summary>
    public class Impl<BLOCK> : BlockExtension<Impl<BLOCK>, BLOCK> where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, ParticleBody.Is<BLOCK>, RigidBody.Is<BLOCK> {
      public Impl(BLOCK block)
        : base(block) {
        Angles = new MockArray<int,RadianAngleBl>() {
            Get = (idx) => AngleProperties[idx][block].Bl().ToRadians(),
            Count = AngleProperties.Count,
        };
        Angles.Set = (idx, item) => Angles.Get(idx).Bind = item;
        Radii = new MockArray<int, DoubleBl>() {
          Get = (idx) => RadiusProperties[idx][block].Bl(), Count = RadiusProperties.Count,
        };
        Radii.Set = (idx, item) => Radii.Get(idx).Bind = item;
      }
      // need the shape!

      internal readonly MockArray<int, RadianAngleBl> Angles;
      internal readonly MockArray<int, DoubleBl> Radii;




      internal static readonly GetProperties<BLOCK, Point> ShapePointProperties;
      internal static readonly GetProperty<BLOCK, Point> InitCenterProperty = "InitCenter".NewProperty<BLOCK, Point>();
      internal static readonly GetProperties<BLOCK, double> AngleProperties;
      internal static readonly GetProperties<BLOCK, double> RadiusProperties;
      static Impl() {
        ShapePointProperties = "ShapePoint".NewProperties<BLOCK, Point>(ParticleBody.Impl<BLOCK>.ParticlesCount);
        AngleProperties = "Angle".NewProperties<BLOCK, double>(ParticleBody.Impl<BLOCK>.ParticlesCount);
        RadiusProperties = "Radius".NewProperties<BLOCK, double>(ParticleBody.Impl<BLOCK>.ParticlesCount);
      }
      /// <summary>
      /// Compute weight of a particle. By default, all particles have the same weight. 
      /// </summary>
      //public Func<ParticleBody.Impl<BLOCK>.Particle, DoubleBl> ParticleWeight = (p) => 1d;

      /// <summary>
      /// Called before center and rotation are computed.
      /// </summary>
      public Action<BLOCK> RelaxFirst {
        set {
          var prev = RelaxFirst0;
          RelaxFirst0 = (blockA) => { prev(blockA); value(blockA); };
        }
      }
      private Action<BLOCK> RelaxFirst0 = (blockA) => { };

      /// <summary>
      /// Called before center/rotation are applied to particle positions.
      /// </summary>
      public Action<BLOCK> RelaxNext {
        set {
          var prev = RelaxNext0;
          RelaxNext0 = (blockA) => { prev(blockA); value(blockA); };
        }
      }
      private Action<BLOCK> RelaxNext0 = (blockA) => { };

      //public Func<PhysicsBlock<BLOCK>.Body, PointBl> Scale = null; // (body) => new PointBl(1d,1d);
      public Func<PhysicsBlock<BLOCK>.Body, DoubleBl> ShapeStrength = body => 1d;
      public Func<int, DoubleBl> ParticleCenterWeight = idx => 1d;


      protected internal override void DoInit(BLOCK block) {

        // ensure particle body is initialized first.
        ForceInit<ParticleBody.Impl<BLOCK>>(block);
        ForceInit<RigidBody.Impl<BLOCK>>(block);

        PointBl InitCenter0 = new PointBl(0, 0);
        var sp = block.ShapePoints();
        {
          DoubleBl TotalWeight = 0d;
          for (int i = 0; i < ShapePointProperties.Count; i++) {
            var weight = ParticleCenterWeight(i);
            InitCenter0 += (sp[i] * weight);
            TotalWeight += weight;
          }
          InitCenter0 = InitCenter0 / TotalWeight;
        }
        block.InitCenter().Bind = InitCenter0;

        for (int i = 0; i < ShapePointProperties.Count; i++) {
          var v = ((sp[i]) - block.InitCenter());
          Angles[i] = v.Angle.Normalize;
          Radii[i] = v.Length;
        }
        RelaxFirst0(block);
        block.ForAll(body => {
          DoubleBl scale = body.Scale(); //Scale == null ? new PointBl(1,1) : Scale(body);
          PointBl Rotation0 = new PointBl(0, 0);
          for (int i = 0; i < body.Particles().Count; i++) {

            var vector = body.Particles()[i].Position - body.Center();
            vector = vector / scale;
            Rotation0 += (vector.Angle - Angles[i]).ToPoint();
          }
          body.Center().Bind = body.ComputedCenter(ParticleCenterWeight);
          body.Rotation().Bind = Rotation0.Angle;
        });
        RelaxNext0(block);
        block.ForAll(body => {
          DoubleBl scale = body.Scale(); // Scale == null ? new PointBl(1, 1) : Scale(body);
          body.Particles().ForAll(particle => {
            particle.Position.Relax[ShapeStrength(body)] =
              body.Center() + (body.Rotation() + Angles.ToArray().Table(particle.Index)).ToPoint() *
              Radii.ToArray().Table(particle.Index) * scale;
          });
        });
      }
    }
    /// <summary>
    /// Access shape body extension for this block.
    /// </summary>
    public static Impl<BLOCK> ShapeBodyE<BLOCK>(this PhysicsBlock<BLOCK> block)  
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, ParticleBody.Is<BLOCK>, RigidBody.Is<BLOCK> {
      return block.Extension<Impl<BLOCK>>();
    }

    public static PointBl InitCenter<BLOCK>(this PhysicsBlock<BLOCK> block)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, ParticleBody.Is<BLOCK>, RigidBody.Is<BLOCK> {
      return Impl<BLOCK>.InitCenterProperty[(BLOCK)block];
    }

    public static void Pin<BLOCK>(this PhysicsBlock<BLOCK> block, PointBl Local, Func<PhysicsBlock<BLOCK>.Body,PointBl> Global, Func<PhysicsBlock<BLOCK>.Body,BoolBl> Guard, DoubleBl Strength)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, ParticleBody.Is<BLOCK>, RigidBody.Is<BLOCK> {
      block.Pin(Local, Global, Guard, Strength, body => body.Scale(), block.ShapePoints());


    }

    /// <summary>
    /// Access shape point dependency properties of this block. 
    /// </summary>
    public static PointBl[] ShapePoints<BLOCK>(this PhysicsBlock<BLOCK> block)
      where BLOCK : PhysicsBlock<BLOCK>, Is<BLOCK>, ParticleBody.Is<BLOCK>, RigidBody.Is<BLOCK> {
      var points = new PointBl[Impl<BLOCK>.ShapePointProperties.Count];
      for (int i = 0; i < points.Length; i++)
        points[i] = Impl<BLOCK>.ShapePointProperties[i][(BLOCK) block];
      return points;
    }
  }
}